package data.vectors;


/**
 * This class describe a vector of doubles
 * The features are indexed from 0 to size()-1
 * @author denoyer
 *
 */

public abstract class DoubleVector {
	/**
	 * Return the size of the vector (features from 0 to N-1)
	 */
	public abstract int size();
	
	/**
	 * 	Return the value of a component of the vector
	 *@params i the number of the component
	 */
	public abstract double getValue(int i);
	
	/**
	 * get the number of non null values
	 */
	public abstract int getNumberNonNullValues();
	
	/**
	 * Return an interator over the (feature,value) pairs
	 */
	public abstract DoubleVectorIterator getIterator();
	
	/**
	 * Return an iterator over the non null values of the vector
	 */
	public abstract DoubleVectorIterator getNonNullIterator();
	
	/*
	 * Return the dot product
	 */
	public final double computeDOTProduct(DoubleVector v)
	{
		DoubleVector v1=this;
		DoubleVector v2=v;
		
		if(v1.getNumberNonNullValues()>v2.getNumberNonNullValues()){
			v1=v; v2=this;
		}
			

		DoubleVectorIterator it=v1.getNonNullIterator();
		double score=0.0;
		while(it.hasNext())
		{
			it.next();
			double val=it.getCurrentValue();
			int feat=it.getCurrentFeature();
			/*if (feat<d)*/ score+=val*v2.getValue(feat);
		}
		
		return(score);
	}
	
	public double computeDOTProduct(double []v)
	{
		DoubleVector v1=this;
		
		DoubleVectorIterator it=v1.getNonNullIterator();
		double score=0.0;
		while(it.hasNext())
		{
			it.next();
			double val=it.getCurrentValue();
			int feat=it.getCurrentFeature();
			score+=val*v[feat];
		}
		return(score);		
	}
	
	public double normSquare()
	{
		DoubleVectorIterator it=getNonNullIterator();
		double norm=0.0;
		while(it.hasNext())
		{
			it.next();
			double val=it.getCurrentValue();
			norm+=val*val;
		}
		return(norm);
	}
	
	
	public String toString()
	{
		StringBuffer sb=new StringBuffer();
		DoubleVectorIterator it=getIterator();
		int nb=0;
		while(it.hasNext())
		{
			it.next();
			double val=it.getCurrentValue();
			int fea=it.getCurrentFeature();
			if (val!=0)
			{
				if (nb!=0) sb.append(" ");
				nb++;
				sb.append(fea);
				sb.append(":");
				sb.append(val);
			}
		}
		return(sb.toString());
	}	
	
	
	public boolean equals(Object o)
	{
		if (o==null) return(false);
		DoubleVector v=(DoubleVector)o;
		if (v.size()!=size()) return(false);
		return(computeDOTProduct(v)==normSquare());
	}
}
